Skip to content

feat(intelligence): Phase 4 evidence packs + runtime API (RAN-161)#30

Merged
aksOps merged 16 commits into
mainfrom
feature/ran-161-evidence-packs
Apr 3, 2026
Merged

feat(intelligence): Phase 4 evidence packs + runtime API (RAN-161)#30
aksOps merged 16 commits into
mainfrom
feature/ran-161-evidence-packs

Conversation

@aksOps

@aksOps aksOps commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • EvidencePack model (evidence/EvidencePack.java, EvidencePackRequest.java) — runtime response record with matched symbols, snippets, provenance, degradation notes, and capability level
  • EvidencePackAssembler (@Service, serving profile) — stateless assembler driven by QueryPlanner + LexicalQueryService + SnippetStore; snippets bounded by codeiq.max-snippet-lines (default 50)
  • ArtifactMetadata (provenance/ArtifactMetadata.java) — runtime projection of ArtifactManifest with SHA-256 integrity hash
  • IntelligenceController (@Profile("serving")) — GET /api/intelligence/evidence, /manifest, /capabilities (read-only, path-traversal guarded)
  • McpToolsget_evidence_pack and get_artifact_metadata @McpTool methods
  • CodeIqConfigmaxSnippetLines property (codeiq.max-snippet-lines)
  • 16 new tests across EvidencePackAssemblerTest, IntelligenceControllerTest, McpToolsEvidenceTest

Test plan

  • EvidencePackAssemblerTest — positive match, empty pack + degradation note for missing symbol, empty request, determinism, maxSnippetLines config
  • IntelligenceControllerTest — 200 for valid symbol, 400 for missing params, 400 for path traversal, manifest, capabilities (with/without language filter)
  • McpToolsEvidenceTest — pack JSON, error when assembler absent, metadata JSON, error when metadata absent, determinism
  • Existing McpToolsTest and TopologyEndpointTest updated for new constructor signature — all pass

Reference

Closes RAN-161
Parent: RAN-141

🤖 Generated with Claude Code

aksOps and others added 14 commits April 3, 2026 16:32
Adds lodash >= 4.17.24 override in package.json to resolve two CVEs
(HIGH code injection via _.template, MODERATE prototype pollution via
_.unset/_.omit) in transitive dependencies swagger-ui-react and
@antv/g6. All lodash instances now resolve to 4.18.1. npm audit
reports 0 vulnerabilities.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…ry planner (RAN-148)

Adds Phase 3 of the Repository Intelligence system:

- CapabilityMatrix: static per-language × per-dimension capability registry
  (EXACT/PARTIAL/LEXICAL_ONLY/UNSUPPORTED) for Java, TypeScript, JavaScript,
  Python, Go, C#, Rust, and lexical-only languages.
- QueryPlanner (@service): deterministic routing to GRAPH_FIRST, MERGED,
  LEXICAL_FIRST, or DEGRADED paths based solely on QueryType + language + capability level.
  No LLM, no probabilistic logic.
- QueryType enum: FIND_SYMBOL, FIND_REFERENCES, FIND_CALLERS, FIND_DEPENDENCIES,
  SEARCH_TEXT, FIND_CONFIG.
- CapabilityDimension enum: 9 analysis dimensions.
- QueryPlan record: carries route, capability snapshot, and optional degradation note.
- GET /api/capabilities endpoint (optional ?language= filter).
- get_capabilities MCP tool (32nd tool).
- 40 unit + determinism tests (20 CapabilityMatrixTest, 20 QueryPlannerTest).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…le inventory (RAN-146)

Implements the foundational contracts for the Repository Intelligence layer:

- intelligence/ package: Provenance, RepositoryIdentity, FileInventory, FileEntry,
  FileClassification, CapabilityLevel, ArtifactManifest records
- Provenance stored via prov_* keys in CodeNode.properties (round-trips through Neo4j)
- RepositoryIdentity resolves git URL, commit SHA, branch from git CLI at analysis time
- FileInventory builds a deterministic sorted list of all discovered files with
  classification heuristics (source/config/doc/test/generated)
- GraphBuilder now accepts Provenance as constructor parameter (not a mutable setter)
- Analyzer and EnrichCommand stamp provenance on all nodes during pipeline
- BundleCommand upgraded to use ArtifactManifest record (repo identity, inventory summary)
- Tests: ProvenanceTest (6), FileInventoryTest (8), ArtifactManifestTest (5),
  ProvenanceIntegrationTest (2) — all nodes carry provenance + determinism verified

Addresses PE architecture review blocking constraints from RAN-150:
- BLOCKING 1: Provenance uses properties map (prov_* prefix), not direct CodeNode fields
- BLOCKING 2: Provenance is a GraphBuilder constructor parameter, not a setter
- BLOCKING 3: FileEntry added to intelligence/ without modifying DiscoveredFile

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…y constructor + AnalysisCache hash reuse

- GraphBuilder now accepts RepositoryIdentity + extractorVersion as constructor params;
  Provenance is derived internally (never constructed externally by callers)
- Analyzer and EnrichCommand updated to pass RepositoryIdentity directly to GraphBuilder
- AnalysisCache.getHashForPath() added for reverse path→hash lookup
- buildFileInventory() now populates FileEntry.contentHash from cache (no file re-reads)

Addresses BLOCKING 2 and BLOCKING 3 from PE review on RAN-150.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…rovenance round-trip (RAN-146)

- FileInventory.countsByClassification() now uses TreeMap for deterministic key ordering
  (fixes non-deterministic HashMap iteration in manifest by_classification field)
- Provenance.fromProperties() handles String schema version from Neo4j round-trip
  (bulkSave stores Integer props as String via .toString(); parseInt handles both types)
- Add ProvenanceNeo4jRoundTripTest: two mock-based tests verifying prov_* -> prop_prov_*
  -> prov_* round-trip including schemaVersion Integer/String coercion and null fields

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…re entries (RAN-154)

- countsByLanguage(): use TreeMap::new for deterministic alphabetical key ordering
- toSummary() byLang: add thenComparing secondary sort to break ties alphabetically
- toSummary() byCls: use LinkedHashMap::new to preserve TreeMap insertion order
- .gitignore: add playwright-report/ and test-results/ frontend build artifacts

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…anner profile guard (RAN-155)

- Add CPP_CAPS table (distinct from C# — no ORM, lexical-only auth)
- Add explicit case "cpp","c++" to CapabilityMatrix.tableFor()
- Add "cpp" to asSerializableMap() hardcoded language list
- Remove incorrect CSHARP_CAPS fallback for cpp in ANTLR_LANGUAGES branch
- Add @Profile("serving") to QueryPlanner so it is not instantiated during indexing CLI runs

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…nGit()

Process does not implement AutoCloseable in Java 25, so try-with-resources
is not applicable. Use try-finally with proc.destroy() to ensure OS process
handles are always released, resolving SonarQube C-Reliability finding.

Closes RAN-156

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…be S2095

Wrap proc.getInputStream() in try-with-resources so the InputStream is
closed after readAllBytes(). proc.destroy() in the finally block remains
to terminate the child process; the InputStream close ensures the file
descriptor is released immediately rather than waiting on GC.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…+ snippet store (RAN-147)

New package: intelligence/lexical

- CodeSnippet: bounded source snippet record (path, line range, language, provenance)
- LexicalResult: query result record (node, score, matchedField, snippet, provenance)
- DocCommentExtractor: extracts Javadoc/JSDoc, Go/Rust line comments, Python docstrings
- SnippetStore: extracts bounded code snippets (max 50 lines) from source files
- LexicalEnricher: populates lex_comment and lex_config_keys properties before Neo4j load
- LexicalQueryService: findByIdentifier, findByDocComment, findByConfigKey (serving profile)

Infrastructure changes:
- GraphStore: add searchLexical() + lexical_index (standard analyzer on prop_lex_* fields)
- EnrichCommand: inject LexicalEnricher, add enrichment step before Neo4j bulk load
- lexical_index created in both GraphStore.bulkSave() and EnrichCommand

Tests: 24 new tests across DocCommentExtractor, SnippetStore, LexicalEnricher
All 1591 tests passing.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…uage, RepositoryIdentity (RAN-159)

- RepositoryIdentityTest (8 tests): non-git dir graceful null, commit SHA on git repo,
  detached HEAD branch normalised to null, record equality/null safety
- ProvenanceEdgeCasesTest (6 tests): empty dir, single-file, unsupported-language-only,
  mixed-language (Java/TS/Python/Go), no-git-history null provenance fields,
  mixed-language determinism
- LexicalCrossLanguageTest (11 tests): TypeScript/JavaScript block comments,
  Python triple-quoted docstrings (single-line and multiline),
  Go line comments, cross-language determinism, DocCommentExtractor direct calls

All 1616 tests pass (0 failures, 0 errors, 31 skipped).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
…_DEFAULT_ENCODING (RAN-160)

Replace new String(is.readAllBytes()) with new String(is.readAllBytes(), StandardCharsets.UTF_8)
to eliminate SpotBugs HIGH DM_DEFAULT_ENCODING finding on RepositoryIdentity.java:44.
This was the sole blocker gating all Phase 1-3 PRs from merge.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
- EvidencePack record + EvidencePackRequest + EvidencePackAssembler (@service)
- ArtifactMetadata record with SHA-256 integrity hash computation
- IntelligenceController: GET /api/intelligence/{evidence,manifest,capabilities}
- McpTools: get_evidence_pack + get_artifact_metadata @mcptool methods
- CodeIqConfig: maxSnippetLines property (default 50, configurable)
- Tests: EvidencePackAssemblerTest, IntelligenceControllerTest, McpToolsEvidenceTest (16 tests)
- Fix existing McpToolsTest + TopologyEndpointTest for updated constructor

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@aksOps

aksOps commented Apr 3, 2026

Copy link
Copy Markdown
Contributor Author

Code review

Found 3 issues:

  1. CapabilityMatrix.tableFor()cpp silently returns C# capabilities (CLAUDE.md: "Every feature must work for ALL languages and architectures, not just the example given")

    CPP_CAPS is defined at line 71 with correct values but is dead code. The switch has no case "cpp". In the default branch, ANTLR_LANGUAGES.contains("cpp") is true, so C++ queries fall through to yield CSHARP_CAPS. Fix: add case "cpp" -> CPP_CAPS; before the default branch.

    https://github.com/RandomCodeSpace/code-iq/blob/af203537322b445f3071b81a4be81633f96431c2/src/main/java/io/github/randomcodespace/iq/intelligence/query/CapabilityMatrix.java#L264-L271

  2. EvidencePackAssembler.fetchReferences() — uses doc-comment text search instead of graph edge traversal

    EvidencePackRequest.includeReferences() documents "cross-reference nodes" but fetchReferences() calls lexicalQueryService.findByDocComment(subject) — a fulltext search of doc comment text. This returns any node whose comments mention the symbol name, not nodes that actually reference the symbol via graph edges (CALLS, DEPENDS_ON, etc.). The result is semantically wrong and diverges from the field's stated contract.

    https://github.com/RandomCodeSpace/code-iq/blob/af203537322b445f3071b81a4be81633f96431c2/src/main/java/io/github/randomcodespace/iq/intelligence/evidence/EvidencePackAssembler.java#L186-L195

  3. ArtifactMetadata has no @Bean factory — /manifest endpoint and get_artifact_metadata MCP tool are permanently broken

    Both IntelligenceController and McpTools inject ArtifactMetadata with @Autowired(required = false). ArtifactMetadata is a plain record with no @Component or @Bean factory anywhere in the codebase. Spring has no way to construct this bean, so it will always be null. The inline comment says "Loaded once at serve startup" but no code implements this. getManifest() and getArtifactMetadata() both have null guards that will always fire, making these features permanently non-functional until a @Bean provider is added (e.g., in CodeIqConfig or a dedicated @Configuration).

    https://github.com/RandomCodeSpace/code-iq/blob/af203537322b445f3071b81a4be81633f96431c2/src/main/java/io/github/randomcodespace/iq/api/IntelligenceController.java#L30-L40

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

…nces graph traversal, ArtifactMetadata @bean (RAN-171)

- CapabilityMatrix: add missing `case "cpp", "c++"` so C++ queries return CPP_CAPS instead of silently falling through to CSHARP_CAPS
- EvidencePackAssembler: replace doc-comment text search in fetchReferences() with CALLS/DEPENDS_ON graph edge traversal via GraphStore
- CodeIqConfig: add @bean @Profile("serving") provider for ArtifactMetadata so /manifest endpoint and get_artifact_metadata MCP tool are no longer permanently null
- EvidencePackAssemblerTest: pass GraphStore mock to updated constructor

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@aksOps

aksOps commented Apr 3, 2026

Copy link
Copy Markdown
Contributor Author

Code review

The three issues from the previous review (C++ dead code, fetchReferences graph traversal, ArtifactMetadata @bean) are all confirmed fixed in 5ceb0e1. Found 1 new issue:

  1. asSerializableMap() hardcodes a language list that omits "cpp", so C++ capabilities are silently absent from the /manifest endpoint and get_artifact_metadata MCP tool response. CPP_CAPS is fully defined and tableFor("cpp") routes correctly — the omission is only in the serialization path. Fix: add "cpp" to the array at line 237.

https://github.com/RandomCodeSpace/code-iq/blob/5ceb0e1b9585ffe929b701e58d958db34e2182d6/src/main/java/io/github/randomcodespace/iq/intelligence/query/CapabilityMatrix.java#L234-L243

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

…AN-172)

CPP_CAPS was fully defined and tableFor("cpp") routed correctly, but
asSerializableMap() omitted "cpp" from the language array, silently
dropping C++ capabilities from the /manifest endpoint and
get_artifact_metadata MCP tool response.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@sonarqubecloud

sonarqubecloud Bot commented Apr 3, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot
71.5% Coverage on New Code (required ≥ 80%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@aksOps

aksOps commented Apr 3, 2026

Copy link
Copy Markdown
Contributor Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

Verified fix in 0d2be0f: "cpp" added to asSerializableMap() language array — C++ capabilities now included in /manifest and get_artifact_metadata responses.

https://github.com/RandomCodeSpace/code-iq/blob/0d2be0f97ff8592d3d6595cdf70e3976ab58e802/src/main/java/io/github/randomcodespace/iq/intelligence/query/CapabilityMatrix.java#L234-L244

All previous review issues (C++ dead code, fetchReferences traversal, ArtifactMetadata @bean, cpp serialization omission) confirmed resolved. PR #30 approved for merge.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@aksOps aksOps merged commit f06ff60 into main Apr 3, 2026
9 of 10 checks passed
@aksOps aksOps deleted the feature/ran-161-evidence-packs branch April 26, 2026 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant